﻿using JBeamLibrary.VehicleParts.Collections;
using JBeamLibrary.VehicleParts.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JBeamLibrary.VehicleParts.Elements
{
    public class Engine
    {
        #region Fields

        private readonly List<string> _breakableDriveshafts = new List<string>();
        private readonly List<string> _waterDamageGroups = new List<string>();
        private readonly GearCollection _gears = new GearCollection();
        private readonly List<string> _fuelTankBeams = new List<string>();

        #endregion

        #region Properties

        /// <summary>Gets or sets the transmission type</summary>
        public TransmissionType TransmissionType { get; set; }

        /// <summary>Gets the list of gears</summary>
        public GearCollection Gears { get { return _gears; } }

        public float LowShiftDownRPM { get; set; }

        public float LowShiftUpRPM { get; set; }

        public float HighShiftDownRPM { get; set; }

        public float HighShiftUpRPM { get; set; }

        public float ClutchDuration { get; set; }

        public int ViscousCoupling { get; set; }

        public long LockingTorqueLimit { get; set; }

        public bool EnableLocking { get; set; }

        /// <summary>Gets or sets the RPM when the vehicle is not moving</summary>
        public float IdleRPM { get; set; }

        /// <summary>Gets or sets the RPM to reach to shift down</summary>
        public float ShiftDownRPM { get; set; }

        /// <summary>Gets or sets the RPM to reach to shift up</summary>
        public float ShiftUpRPM { get; set; }

        /// <summary>Gets or sets the maximum RPM</summary>
        public float MaxRPM { get; set; }

        /// <summary>Gets or sets the inertia</summary>
        public float Inertia { get; set; }

        /// <summary>Gets or sets the friction</summary>
        public float Friction { get; set; }

        /// <summary>Gets or sets the braking coefficient</summary>
        public float BrakingCoefRPS { get; set; }

        /// <summary>Gets or sets the burn efficiency</summary>
        public float BurnEfficiency { get; set; }

        /// <summary>Gets or sets the throttle sensitivity</summary>
        public float ThrottleSensitivity { get; set; }

        /// <summary>Gets the driveshafts that will be disabled if their linked beams break</summary>
        public List<string> BreakableDriveshafts { get { return _breakableDriveshafts; } }

        /// <summary>Gets the groups that can take water damage</summary>
        public List<string> WaterDamageGroups { get { return _waterDamageGroups; } }

        /// <summary>Gets the fuel tank beams</summary>
        public List<string> FuelTankBeams { get { return _fuelTankBeams; } }

        /// <summary>Gets or sets the fuel capacity</summary>
        public int FuelCapacity { get; set; }
        
        /// <summary>Gets or sets the ABS rate</summary>
        public float ABSRate { get; set; }

        /// <summary>Gets or sets the differential value</summary>
        public float Differential { get; set; }

        /// <summary>Gets or sets the axle friction</summary>
        public float AxleFriction { get; set; }

        /// <summary>Gets a value indicating whether some values have been set or not</summary>
        public bool HasValues
        {
            get
            {
                return
                    Gears.Count > 0 ||
                    LowShiftDownRPM > int.MinValue ||
                    LowShiftUpRPM > int.MinValue ||
                    HighShiftDownRPM > int.MinValue ||
                    HighShiftUpRPM > int.MinValue ||
                    ClutchDuration > float.MinValue ||
                    ViscousCoupling > int.MinValue ||
                    LockingTorqueLimit > long.MinValue ||
                    IdleRPM > float.MinValue ||
                    ShiftDownRPM > float.MinValue ||
                    ShiftUpRPM > float.MinValue ||
                    MaxRPM > float.MinValue ||
                    Inertia > float.MinValue ||
                    Friction > float.MinValue ||
                    BrakingCoefRPS > float.MinValue ||
                    BurnEfficiency > float.MinValue ||
                    ThrottleSensitivity > float.MinValue ||
                    BreakableDriveshafts.Count > 0 ||
                    WaterDamageGroups.Count > 0 ||
                    FuelCapacity > int.MinValue ||
                    FuelTankBeams.Count > 0 ||
                    ABSRate > float.MinValue ||
                    Differential > float.MinValue ||
                    AxleFriction > float.MinValue;
            }
        }

        #endregion

        #region CTORs

        public Engine()
        {
            TransmissionType = TransmissionType.Undefined;
            LowShiftDownRPM = float.MinValue;
            LowShiftUpRPM = float.MinValue;
            HighShiftDownRPM = float.MinValue;
            HighShiftUpRPM = float.MinValue;
            ClutchDuration = float.MinValue;
            ViscousCoupling = int.MinValue;
            LockingTorqueLimit = long.MinValue;
            IdleRPM = float.MinValue;
            ShiftDownRPM = float.MinValue;
            ShiftUpRPM = float.MinValue;
            MaxRPM = float.MinValue;
            Inertia = float.MinValue;
            Friction = float.MinValue;
            BrakingCoefRPS = float.MinValue;
            BurnEfficiency = float.MinValue;
            ThrottleSensitivity = float.MinValue;
            FuelCapacity = int.MinValue;
            ABSRate = float.MinValue;
            Differential = float.MinValue;
            AxleFriction = float.MinValue;
        }

        public Engine(IEnumerable<string> breakableDriveshafts, IEnumerable<string> waterDamageGroups)
            : this()
        {
            BreakableDriveshafts.AddRange(breakableDriveshafts);
            WaterDamageGroups.AddRange(waterDamageGroups);
        }

        public Engine(float idleRpm, float shiftDownRpm, float shiftUpRpm, float maxRpm, float inertia, float friction,
            float brakingCoefRps, float burnEfficiency, float throttleSensitivity)
            : this()
        {
            IdleRPM = idleRpm;
            ShiftDownRPM = shiftDownRpm;
            ShiftUpRPM = shiftUpRpm;
            MaxRPM = maxRpm;
            Inertia = inertia;
            Friction = friction;
            BrakingCoefRPS = brakingCoefRps;
            BurnEfficiency = burnEfficiency;
            ThrottleSensitivity = throttleSensitivity;
        }

        public Engine(float lowShiftDownRPM, float lowShiftUpRPM, float highShiftDownRPM, float highShiftUpRPM, float clutchDuration,
            int viscousCoupling, long lockingTorqueLimit, bool enableLocking)
            : this()
        {
            LowShiftDownRPM = lowShiftDownRPM;
            LowShiftUpRPM = lowShiftUpRPM;
            HighShiftDownRPM = highShiftDownRPM;
            HighShiftUpRPM = highShiftUpRPM;
            ClutchDuration = clutchDuration;
            ViscousCoupling = viscousCoupling;
            LockingTorqueLimit = lockingTorqueLimit;
            EnableLocking = enableLocking;
        }

        #endregion
    }
}
